import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/widgets.dart';

import 'package:scoped_model/scoped_model.dart';

import 'package:flutter_popcorntime/utils/http_util.dart';
import 'package:flutter_popcorntime/api/apis.dart';
import 'package:flutter_popcorntime/models/video_item.dart';
import 'package:flutter_popcorntime/models/json/video_data_json.dart';
import 'package:flutter_popcorntime/constants/constants.dart';

enum StatusModel {
  unknown,
  loading,
  completed,
}

class VideoModel extends Model {
  static final DateTime defaultDateTime = DateTime(2021);

  Map<String, List<VideoItem>> _videoMap = {};

  DateTime _refreshTimeMovies = defaultDateTime;
  DateTime _refreshTimeSeries = defaultDateTime;
  DateTime _refreshTimeAnime = defaultDateTime;

  StatusModel statusModel = StatusModel.unknown;

  static VideoModel of(BuildContext context) =>
      ScopedModel.of<VideoModel>(context, rebuildOnChange: true);

  VideoModel() {
    for (var item in [
      Constants.kTabMovies,
      Constants.kTabSeries,
      Constants.kTabAnime
    ]) {
      _videoMap[item] = [];
    }
  }

  List<VideoItem>? videoList(final String name) => _videoMap[name];

  Future<bool> refreshMoviesList(
      {String sort = "seeds",
      String quality = "720p,1080p,3d",
      int page = 1,
      bool force = false}) async {
    statusModel = StatusModel.loading;
    notifyListeners();

    bool result = false;

    if (force ||
        DateTime.now().difference(_refreshTimeMovies) > Duration(seconds: 30)) {
      try {
        print("Request url: ${Api.moviesUrl}");

        Response response = await HttpUtil().get(
            Api.moviesUrl, {"sort": sort, "quality": quality, "page": page});

        print("Request result: ${response.statusCode}");

        if (HttpStatus.ok == response.statusCode) {
          _refreshTimeMovies = DateTime.now();
          Map resp = response.data as Map;
          List<dynamic> movieList = resp["MovieList"];
          List<VideoItem> items = movieList
              .map((e) => VideoItem()..videoData = VideoData.fromJson(e))
              .toList();
          _videoMap[Constants.kTabMovies] = items;

          result = true;
        }
      } catch (e) {
        print('$e');
      } finally {}
    } else {
      print("refreshMoviesList ignore");
    }

    statusModel = StatusModel.completed;
    notifyListeners();
    return result;
  }

  Future<bool> refreshSeriesList(
      {String sort = "trending",
      int limit = 50,
      String genre = "All",
      int order = -1,
      bool force = false}) async {
    statusModel = StatusModel.loading;
    notifyListeners();

    bool result = false;

    if (force ||
        DateTime.now().difference(_refreshTimeSeries) > Duration(seconds: 30)) {
      try {
        print("Request url: ${Api.seriesUrl}");

        Response response = await HttpUtil().get(Api.seriesUrl,
            {"sort": sort, "limit": limit, "genre": genre, "order": order});

        print("Request result: ${response.statusCode}");

        if (HttpStatus.ok == response.statusCode) {
          _refreshTimeSeries = DateTime.now();

          List resp = response.data as List;
          List<VideoItem> items = [];
          resp.forEach((e) {
            items.add(VideoItem()..videoData = VideoData.fromJson(e));
          });
          _videoMap[Constants.kTabSeries] = items;

          result = true;
        }
      } catch (e) {
        print('$e');
      } finally {}
    } else {
      print("refreshSeriesList ignore");
    }

    statusModel = StatusModel.completed;
    notifyListeners();
    return result;
  }

  Future<bool> refreshAnimeList(
      {String sort = "trending",
      int limit = 50,
      String genre = "All",
      int order = -1,
      bool force = false}) async {
    statusModel = StatusModel.loading;
    notifyListeners();

    bool result = false;

    if (force ||
        DateTime.now().difference(_refreshTimeAnime) > Duration(seconds: 30)) {
      try {
        print("Request url: ${Api.animesUrl}");

        Response response = await HttpUtil().get(Api.animesUrl,
            {"sort": sort, "limit": limit, "genre": genre, "order": order});

        print("Request result: ${response.statusCode}");

        if (HttpStatus.ok == response.statusCode) {
          _refreshTimeAnime = DateTime.now();

          List resp = response.data as List;
          List<VideoItem> items = [];
          resp.forEach((e) {
            items.add(VideoItem()..videoData = VideoData.fromJson(e));
          });
          _videoMap[Constants.kTabAnime] = items;

          result = true;
        }
      } catch (e) {
        print('$e');
      } finally {}
    } else {
      print("refreshAnimeList ignore");
    }

    statusModel = StatusModel.completed;
    notifyListeners();
    return result;
  }

  Future<bool> refreshList(final String name,
      {String sort = "trending",
      int limit = 50,
      String genre = "All",
      int order = -1,
      bool force = false}) async {
    bool result = false;
    switch (name) {
      case Constants.kTabMovies:
        result = await refreshMoviesList(force: force);
        break;
      case Constants.kTabSeries:
        result = await refreshSeriesList(
            sort: sort, limit: limit, genre: genre, order: order, force: force);
        break;
      case Constants.kTabAnime:
        result = await refreshAnimeList(
            sort: sort, limit: limit, genre: genre, order: order, force: force);
        break;
    }
    return result;
  }

  void favorite(VideoItem videoItem, bool favorite) {
    videoItem.favorite = favorite;
    notifyListeners();
  }

  void watched(VideoItem videoItem, bool watched) {
    videoItem.watched = watched;
    notifyListeners();
  }
}
